package util;

import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.LinkedHashMap;

public class Filter {
	public static boolean canUse(Method m) {
		if (m.getName().equals("main")||m.getName().equals("print")||m.getName().equals("outputTestSequence"))
			return false;

		if (!Filter.isVisible(m.getModifiers()))
			return false;

		if (Modifier.isNative(m.getModifiers()))
			return false;

		if (m.getDeclaringClass().equals(java.lang.Object.class))
			return false;// handled here to avoid printing reasons

		if (m.getDeclaringClass().equals(java.lang.Thread.class))
			return false;// handled here to avoid printing reasons

		if (m.isBridge())
	        return false;

		if (m.isSynthetic())
	        return false;
		

		return true;
	}
	 private static Map<Class<?>, Boolean> cached_isVisible =
	     new LinkedHashMap<Class<?>, Boolean>();

	 public static boolean canUse(Class<?> c) {
		 if( Filter.isVisible (c))
			 return true;
		 if(Modifier.isAbstract (c.getModifiers()))
			 return true;
		 
		 return false;
	 
	 }
	 public static boolean isVisible(Class<?> c){

	     Boolean cached = cached_isVisible.get(c);
	     if (cached == null) {
	       if (c.isAnonymousClass()) {
	         cached = false;
	       } else {
	         int mods = c.getModifiers();
	         boolean classVisible = isVisible (mods);
	         if (c.isMemberClass())
	           cached = classVisible && isVisible(c.getDeclaringClass());
	         else
	           cached = classVisible;
	       }
	       cached_isVisible.put(c, cached);
	     }
	     assert cached != null;
	     return cached;
	   }
	  public static boolean isVisible (int modifiers) {
		    // System.out.printf ("isVisible public_only=%b, modifiers = %s%n",
		    //             GenInputsAbstract.public_only, Modifier.toString(modifiers));
		    if (GAConfig.public_only) {
		      return Modifier.isPublic (modifiers);
		    } else {
		      return !Modifier.isPrivate (modifiers);
		    }
		  }

	public static boolean skip(Field field) {
		final int modifiers = field.getModifiers();
		if(!Modifier.isPublic(modifiers)) return true;
		if(!Modifier.isStatic(modifiers)) return true;
		
		return false;
	}

	public static boolean isStringType(Class<?> clz) {
		return clz == java.lang.String.class;
	}
	public static boolean isObjectType(Class<?> clz) {
		return clz ==  java.lang.Object.class;
	}
	public static boolean isPrimitiveOrStringType(Class<?> clz) {
		return clz.isPrimitive() || isPrimitive(clz) || isStringType(clz);
	}

	public static boolean isPrimitive(Class<?> clz) {
		if (clz == java.lang.Boolean.class || clz == java.lang.Character.class
				|| clz == java.lang.Byte.class || clz == java.lang.Short.class
				|| clz == java.lang.Integer.class
				|| clz == java.lang.Float.class || clz == java.lang.Long.class
				|| clz == java.lang.Double.class
				|| clz == java.lang.String.class) {
			return true;
		}
		return false;
	}

	public static String PrimitiveGenericConverter(String type) {
		if (type.equals("int"))
			return Integer.class.getName();
		if (type.equals("long"))
			return Long.class.getName();
		if (type.equals("boolean"))
			return Boolean.class.getName();
		if (type.equals("double"))
			return Double.class.getName();
		if (type.equals("float"))
			return Float.class.getName();

		return type;
	}
	public static boolean isPrivate(Method m) {
		if (Modifier.isAbstract(m.getModifiers())
				|| (Modifier.isPrivate(m.getModifiers()))
				|| Modifier.isNative(m.getModifiers())
				|| Modifier.isProtected(m.getModifiers()))
			return true;
		return false;

	}

}
